import os
import ply.lex as lex

class Lexer:
    keywords = ('VERSION','NS_','BS_','BU_','BO_','SG_', 'EV_', 
        'BA_', 'CM_','BA_DEF_','BA_DEF_DEF_','INT','ENUM',
        'STRING','HEX','FLOAT', 'VAL_', 'SIG_GROUP_', 'VAL_TABLE_', 'BO_TX_BU_')

    tokens = keywords + (
        'EQUALS','PLUS','MINUS','TIMES','DIVIDE','POWER',  # =, +, -, *, /, ^
        'LPAREN','RPAREN','LBRACE','RBRACE','LBK','RBK',   # (, ), {, }, [, ],
        'LT','LE','GT','GE','NE',                          # <, <=, >, >=, !=
        'COLON','COMMA','SEMI','OR','AND','AT',            # :, ,, ;, |, &, @
        'INTEGER','DIGIT','STR','ID','EOL'
    )

    t_EQUALS  = r'='
    t_PLUS    = r'\+'
    t_MINUS   = r'-'
    t_TIMES   = r'\*'
    t_POWER   = r'\^'
    t_DIVIDE  = r'/'
    t_LPAREN  = r'\('
    t_RPAREN  = r'\)'
    t_LBRACE  = r'\{'
    t_RBRACE  = r'\}'
    t_LBK     = r'\['
    t_RBK     = r'\]'
    t_LT      = r'<'
    t_LE      = r'<='
    t_GT      = r'>'
    t_GE      = r'>='
    t_NE      = r'<>'
    t_COLON   = r':'
    t_COMMA   = r'\,'
    t_SEMI    = r';'
    t_OR      = r'\|'
    t_AND     = r'\&'
    t_AT      = r'\@'
    t_INTEGER = r'(0(x|X)[0-9a-fA-F]+)|(\d+)'  
    t_DIGIT   = r'((\d*\.\d+)(E[\+-]?\d+)?|([1-9]\d*E[\+-]?\d+))'
    # t_STR     = r'"(.|\n)*?"'

    def __init__(self):
        out_file = os.path.join("output", "components", "dbc")
        os.makedirs(os.path.dirname(out_file), exist_ok = True)
        self.lexer = lex.lex(module = self, debug = 0, outputdir = out_file)

    def t_STR(self, t):
        r'"(.|\n)*?"'
        t.value = t.value.replace('"', '')
        return t

    def t_ID(self, t):
        r'[_A-Za-z][_A-Za-z0-9]*'
        if t.value in self.keywords:
            t.type = t.value
        return t

    def t_EOL(self, t):
        r'\n'
        # t.lexer.lineno += t.value.count('\n')
        t.lexer.lineno += 1
        t.value = '\n'
        return t

    def t_SPACE(self, t):
        r'\s'

    def t_error(self, t):
        print("Illegal character '%s'" % t.value[0])
        t.lexer.skip(1)


